#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cassert>
using namespace std;

void PrintPending(sigset_t &set)
{
    cout << "Pending bitmap: ";
    for (int i = 31; i >= 1; i--)
    {
        if (sigismember(&set, i))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}
void handler(int sig)
{
    sigset_t pending;
    sigemptyset(&pending);
    sigpending(&pending);
    
    //正在递达2号信号，获取当前的pending
    cout << "递达2号信号时, " ;
    PrintPending(pending);  //0->2号信号在递达前被清零；1->2号信号递达后被清零

    cout << "signo 2 被递达处理... " << endl; 
}
int main()
{

    signal(2, handler); //不让2号信号终止进程
    // 1.屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    // 0.如果屏蔽所有信号，是不是就什么信号都杀不掉进程？
    // 不是，OS不允许有进程不会被所有信号杀掉，规定了9、19号信号无法被屏蔽
    for (int i = 1; i <= 31; i++)
    {
        sigaddset(&block, i);
    }

    // 开始屏蔽
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    assert(n == 0);
    cout << "proc " << getpid() << " block signal 2 success..." << endl;

    int cnt = 0;
    while (true)
    {
        // 2.获取pending位图
        sigset_t pending;
        sigemptyset(&pending);
        n = sigpending(&pending);

        assert(n == 0);
        // 3.打印pending位图
        PrintPending(pending);
        cnt++;

        // 还想看到2号信号从1->0。递达2号信号
        // 4.解除对2号信号的屏蔽
        if (cnt == 10)
        {
            cout << "解除对2号信号的屏蔽..." << endl;
            n = sigprocmask(SIG_UNBLOCK, &block, &oblock);  //一旦解除屏蔽后，2号信号会被立即递达
            assert(n == 0);
        }
        sleep(1);
    }

    // //没有涉及到对内核数据的访问
    // //sigset_t 是一个类型，和int class 没有任何差别，是在栈上开辟的空间
    // sigset_t s;
    // sigemptyset(&s);
    // sigaddset(&s, 2);

    // pid_t id = fork();
    // if (id == 0)
    // {
    //     //child
    //     sleep(2);
    //     int a = 10;
    //     a /= 0;
    //     exit(0);
    // }
    // //parent
    // int status = 0;
    // pid_t rid = waitpid(id, &status, 0);
    // cout << "exit signal: " << (status & 0x7f) << endl;
    // cout << "exit code: " << ((status >> 8) & 0xff) << endl;
    // cout << "exit core: " << ((status >> 7) & 0x1) << endl;
    return 0;
    // int a = 10;
    // a /= 0; //SIGFPE core退出
    // while (true) sleep(1);
}
